pragma Singleton
import QtQuick 2.0
import Qt.labs.settings 1.0
import QtQuick.LocalStorage 2.0

Item {
    id: root
    QtObject {
        id: pri_var

        property string appIDHeader: "X-Bmob-Application-Id"
        property string rEST_API_Key: "X-Bmob-REST-API-Key"
        property string content_type: "application/json"

        property string appId: "83d2fcfb546230440119aa7a346e182a"
        property string aPIKey: "110ae5fe33083afb0892b500b425db5e"

        property string userUrl: "https://api.bmob.cn/1/users"
        property string groupUrl: "https://api.bmob.cn/1/classes/Group"
        property string ugUrl: "https://api.bmob.cn/1/classes/userGroup"
        property string ugTimeUrl: "https://api.bmob.cn/1/classes/ugTime"

        property string userLogin: "https://api.bmob.cn/1/login"
        property string session: ""
        property string currentUserObjectId: ""

        property string dataBaseName: "myDataBase"
        property var db: undefined
        property var dbTableName: ["userModel", "groupModel", "ugModel", "currentUsersGroups"]
    }

    Component.onCompleted: {
        root.initDB()
        root.readDB()
    }
    Component.onDestruction: {
        root.storeDB()
    }
    Settings {
        id: localSettings
        property alias session: pri_var.session
        property alias currentUserObjectId: pri_var.currentUserObjectId
    }


    property ListModel groupModel: groupModel
    //TODO 本地存储
    ListModel {
        id: userModel
    }
    ListModel {
        id: groupModel
    }
    ListModel {
        id: ugModel
    }
    ListModel {
        id: currentUsersGroups
    }
    ListModel{
        id:goalModel
    }

    function initDB() {
        pri_var.db = LocalStorage.openDatabaseSync(pri_var.dataBaseName, "1.0",
                                                   "Example")
        console.log("initDB...")
        pri_var.db.transaction(function (tx) {
            console.log("createDB...")
            for (var i = 0; i != pri_var.dbTableName.length; ++i) {

                var sql = 'CREATE TABLE IF NOT EXISTS %1(objectid TEXT PRIMARY KEY,value TEXT)'
                console.debug("SQLL::" + sql.arg(pri_var.dbTableName[i]))
                var tsql = sql.arg(pri_var.dbTableName[i])
                tx.executeSql(tsql)
            }
        })
    }
    function readDB() {

        console.log("ReadDB...")
        if (pri_var.db === undefined) {
            return
        }
        for (var i = 0; i !== pri_var.dbTableName.length; ++i) {

            pri_var.db.transaction(function (tx) {
                var sql = 'SELECT * FROM %1'
                var tsql = sql.arg(pri_var.dbTableName[i])
                var result = tx.executeSql(tsql)
                for (var j = 0; j !== result.rows.length; ++j) {
                    var value = result.rows[j].value
                    eval(pri_var.dbTableName[i]).append(JSON.parse(value))
                    console.debug("READ RESULT:" + eval(
                                      pri_var.dbTableName[i]).get(j))
                }
            })
        }
    }
    function storeDB() {
        console.log("StoreDB...")
        if (pri_var.db === undefined) {
            return
        }
        for (var i = 0; i !== pri_var.dbTableName.length; ++i) {
            for (var j = 0; j !== eval(pri_var.dbTableName[i]).count; ++j) {
                pri_var.db.transaction(function (tx) {

                    var sql = 'SELECT * FROM %1 WHERE objectid=\'%2\''
                    var tableName = pri_var.dbTableName[i]
                    var item = eval(pri_var.dbTableName[i]).get(j)
                    var tsql = sql.arg(tableName).arg(item.objectId)
                    console.debug("STORE DB:" + tsql)
                    var result = tx.executeSql(tsql)
                    var sobj = JSON.stringify(item)
                    if (result.rows.length === 1) {
                        //UPDATE
                        console.log("EXISTS,UPDATE IT")
                        var sql = "UPDATE %1 SET value=\'%2\' WHERE objectid=\'%3\'".arg(
                                    tableName).arg(sobj).arg(item.objectId)
                        console.debug("STORE DB:" + sql)
                        tx.executeSql(sql)
                    } else {
                        //INSERT
                        var sql = "INSERT INTO %1 VALUES(\'%2\',\'%3\')".arg(
                                    tableName).arg(item.objectId).arg(sobj)
                        console.debug("INSERT SQL:" + sql)
                        tx.executeSql(sql)
                    }
                })
            }
        }
    }

    signal createUserSuccessed(var msg)
    signal createUserFailed(var msg)

    signal createGroupSuccessed(var msg)
    signal createGroupFailed(var msg)

    signal deleteGroupSuccessed(var msg)
    signal deletegroupFailed(var msg)

    signal userJoinGroupSuccessed(var msg)
    signal userJoinGroupFailed(var msg)

    signal userOutGroupSuccessed(var msg)
    signal userOutGroupFailed(var msg)

    signal goalGetSuccessed(var msg)
    signal goalGetFailed(var msg)

    signal getAllGroupsCompleted(var msg)

    signal getUserGroupsSuccessed(var msg)
    signal getUserGroupsFailed(var msg)

    signal userLoginSuccessed(var msg)
    signal userLoginFailed(var msg)


    signal updateUserInfoSuccessed(var msg)
    signal updateUserInfoFailed(var msg)

    signal updateGroupInfoSuccessed(var msg)
    signal updateGroupInfoFailed(var msg)
    function doNetwork(method, url, mdata, mcallback) {

        var xhr = new XMLHttpRequest()

        console.log("doNetworkURL:" + url)
        xhr.open(method, url, true)
        xhr.setRequestHeader(pri_var.appIDHeader, pri_var.appId)
        xhr.setRequestHeader(pri_var.rEST_API_Key, pri_var.aPIKey)
        xhr.setRequestHeader("Content-Type", pri_var.content_type)

        xhr.onreadystatechange = mcallback.bind(undefined, xhr)

        switch (method) {
        case "POST":
            xhr.send(mdata)
            break
        case "DELETE":
            xhr.send()
            break
        case "GET":
            xhr.send()
            break
        }
    }

    function createUser(UName, UPassword, UGender, UAge, UMail, UPhone) {
        var g = {
            username: UName,
            password: UPassword,
            gender: UGender,
            age: parseInt(UAge),
            email: UMail,
            mobilePhoneNumber: UPhone
        }
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) {

                console.log("Headers -->")
                console.log(xhr.getAllResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 201) {
                    var j = JSON.parse(xhr.responseText)
                    g.createdAt = j.createdAt
                    g.objectId = j.objectId
                    g.sessionToken = j.sessionToken
                    userModel.append(g)
                    console.log("responseText Got")
                    emit: createUserSuccessed(xhr.responseText)
                } else {
                    console.error(xhr.status + "|||" + xhr.responseText)
                    emit: createUserFailed(xhr.responseText)
                }
            }
        }
        var test = JSON.stringify(g)
        doNetwork("POST", pri_var.userUrl, test, callback)
    }

    function createGroup(gName, leaderID, gAddress, gDeadline, gGoal) {
        var g = {
            groupName: gName,
            leader: {
                __type: "Pointer",
                className: "_User",
                objectId: leaderID
            },
            location: {
                __type: "GeoPoint",
                latitude: 50.934755,
                longitude: 24.52065
            },
            deadline: {
                __type: "Date",
                iso//TODO resolve gDeadline
                : "2011-08-21 18:02:52"
            },
            goal: gGoal
        }
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 201) {
                    var j = JSON.parse(xhr.responseText)
                    g.createAt = j.createdAt
                    g.objectId = j.objectId
                    groupModel.append(g)
                    emit: createGroupSuccessed(xhr.responseText)
                } else {
                    emit: createGroupFailed(xhr.responseText)
                }
            }
        }

        doNetwork("POST", pri_var.groupUrl, JSON.stringify(g), callback)
    }

    function deleteGroup(GID) {
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    console.log("responseText Got:" + xhr.responseText)
                    emit: deleteGroupSuccessed(xhr.responseText)
                } else {
                    emit: deletegroupFailed(xhr.responseText)
                }
            }
        }

        doNetwork("DELETE", pri_var.groupUrl + "/" + GID, "", callback)
    }

    function userJoinGroup(UID, GID) {

        var g = {
            user: {
                __type: "Pointer",
                className: "_User",
                objectId: UID
            },
            group: {
                __type: "Pointer",
                className: "Group",
                objectId: GID
            }
        }
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Header -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 201) {
                    console.log("responseText Got:" + xhr.responseText)
                    emit: userJoinGroupSuccessed(xhr.responseText)
                } else {
                    console.log("ERROR" + xhr.responseText)
                    emit: userJoinGroupFailed(xhr.responseText)
                }
            }
        }

        doNetwork("POST", pri_var.ugUrl ,JSON.stringify(g), callback)
    }

    function userOutGroup(UID, GID) {
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    console.log("responseText Got:" + xhr.responseText)

                    var jobj = JSON.parse(xhr.responseText)
                    var obId = jobj.results[0].objectId
                    deleteUserGroup(obId)
                }
            }
        }

        doNetwork("GET",
                  pri_var.ugUrl + "?where={\"user\":\"" + UID + "\",\"group\":\"" + GID + "\"}",
                  "", callback)
    }

    function deleteUserGroup(obId) {
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    console.log("responseText Got:" + xhr.responseText)
                    emit: userOutGroupSuccessed(xhr.responseText)
                } else {
                    emit: userOutGroupFailed(xhr.responseText)
                }
            }
        }

        doNetwork("DELETE", pri_var.ugUrl + "/" + obId, "", callback)
    }

    function goalGet(UID, GID, dateTime) {
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    console.log("responseText:" + xhr.responseText)

                    var jobj = JSON.parse(xhr.responseText)
                    var obId = jobj.results[0].objectId
                    goalDoReal(obId, dateTime)
                }
            }
        }

        doNetwork("GET",
                  pri_var.ugUrl + "?where={\"user\":\"" + UID + "\",\"group\":\"" + GID + "\"}",
                  "", callback)
    }

    function goalDoReal(obId, dateTime) {
        var data = {
            usergroupid: {
                __type: "Pointer",
                className: "userGroup",
                objectId: obId
            },
            signintime: {
                __type: "Date",
                iso: "2011-08-21 18:02:52"
            }
        }
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 201) {
                    var j = JSON.parse(xhr.responseText)
                    data.createAt = j.createdAt
                    data.objectId = j.objectId
                    goalModel.append(data)
                    //TODO ??
                    emit:goalGetSuccessed(xhr.responseText)
                }else{
                    emit:goalGetFailed(xhr.responseText)
                }
            }
        }

        doNetwork("POST", pri_var.ugTimeUrl, JSON.stringify(data), callback)
    }

    function getAllGroups() {
        //这里需要清除一下groupModel
        groupModel.clear()
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    console.log("responseText Got:" + xhr.responseText)
                }
                var jobj = JSON.parse(xhr.responseText)
                var results = jobj.results
                var i = 0
                for (; i !== results.length; ++i) {
                    var item = results[i]
                    groupModel.append(item)
                    if (item.leader === localSettings.currentUserObjectId) {
                        currentUsersGroups.append(item)
                    }
                }
                emit: getAllGroupsCompleted(groupModel.count)
                console.log("groupModel Count:" + groupModel.count)
            }
        }
        doNetwork("GET", pri_var.groupUrl + "?include=leader", "", callback)
    }

    /**
      * {
        "results":[
            {
                "createdAt":"2018-04-11 17:44:00",
                "group":{
                    "__type":"Object",
                    "className":"Group",
                    "objectId":"eaeca3e012",
                    "createdAt":"2018-04-08 12:12:15",
                    "deadline":{
                        "__type":"Date",
                        "iso":"2011-08-21 18:02:52"
                    },
                    "goal":"test",
                    "groupName":"test",
                    "leader":{
                        "__type":"Pointer",
                        "className":"_User",
                        "objectId":"9046cb1d3a"
                    },
                    "location":{
                        "__type":"GeoPoint",
                        "latitude":50.934755,
                        "longitude":24.52065
                    },
                    "objectId":"eaeca3e012",
                    "updatedAt":"2018-04-08 12:12:15"
                },
                "objectId":"fb0dabd729",
                "updatedAt":"2018-04-11 17:44:00",
                "user":{
                    "__type":"Pointer",
                    "className":"_User",
                    "objectId":"fa74c9edaf"
                }
            }
            ]

            发出信号userGroupsGot(json)

        }
      **/
    function getUserGroups(UID) {
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    console.log("responseText Got:" + xhr.responseText)
                    var jobj = JSON.parse(xhr.responseText)
                    console.log("responseText:" + jobj.results)
                    var results = jobj.results
                    var i = 0

                    var list = [{

                                }]
                    for (; i !== results.length; ++i) {
                        var item = results[i].group
                        list[i] = item
                    }
                    console.log("userGroupsGet.group_JSON:" + JSON.stringify(
                                    list))
                    emit: getUserGroupsSuccessed(JSON.stringify(list))
                } else {
                    console.error("CALLBACK_ERROR:" + xhr.responseText)
                    emit: getUserGroupsFailed(xhr.responseText)
                }
            }
        }
        var param = {
            user: {
                __type: "Pointer",
                className: "_User",
                objectId: UID
            }
        }

        var sparam = JSON.stringify(param)

        var url = pri_var.ugUrl + "?where=" + sparam + "&include=group"
        doNetwork("GET", url, "", callback)
    }

    /**{	用户格式
     *   	"age":14,
     *   	"createdAt":"2018-04-08 12:18:39",
     *   	"email":"ere@qq.com",
     *   	"gender":"male",
     *   	"mobilePhoneNumber":"18003721234",
     *   	"objectId":"fa74c9edaf",
     *   	"sessionToken":"d529ad1940008293804fb158e3eef978",
     *   	"updatedAt":"2018-04-08 12:18:39",
     *   	"username":"test"
     *	}
     **/

    /**
      * 登录成功发出userLoginSuccessed()信号
      * 失败发出userLoginFailed(msg)信号
      *
      **/
    function userLogin(UPhone, UPassword) {
        var callback = function (xhr) {
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                console.log("responseText Got:" + xhr.responseText)
                if (xhr.status === 200) {
                    var obj = JSON.parse(xhr.responseText)
                    userModel.append(obj)
                    localSettings.session = obj.sessionToken
                    localSettings.currentUserObjectId = obj.objectId
                    emit: userLoginSuccessed(xhr.responseText)
                } else {
                    emit: userLoginFailed(xhr.responseText)
                }
            }
        }
        doNetwork("GET",
                  pri_var.userLogin + "?username=" + UPhone + "&password=" + UPassword,
                  "", callback)
    }
    /**
      * 返回用户对象
      * 若没有用户则返回对象中msg给出错误信息
      *
      **/
    function getUserInfo() {
        var i = 0
        if (localSettings.currentUserObjectId === "") {
            return {
                msg: "用户没登录"
            }
        }

        for (i = 0; i != userModel.count; ++i) {
            if (userModel.get(i).objectId === localSettings.currentUserObjectId)
                return userModel.get(i)
        }
        return {
            msg: "用户没找到" + localSettings.currentUserObjectId
        }
    }
    function updateUserInfo(user){
        for(var i=0;i!=userModel.count;++i){
            if(userModel.get(i).objectId===user.objectId){
                userModel.set(i,user)
            }
        }
        var objid=user.objectId
        user.objectId=undefined
        user.createAt=undefined
        user.updateAt=undefined

        var callback=function(xhr){
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                console.log("responseText Got:" + xhr.responseText)
                if (xhr.status === 200) {
                    emit:updateUserInfoSuccessed(xhr.responseText)
                } else {
                    emit:updateUserInfoFailed(xhr.responseText)
                }
                }
        }


        doNetwork("PUT",pri_var.userUrl+"/"+user.objectId,JSON.stringify(user),callback)

    }

    function updateGroupInfo(group){

        for(var i=0;i!=groupModel.count;++i){
            if(groupModel.get(i).objectId===group.objectId){
                groupModel.set(i,group)
            }
        }
        var objid=group.objectId

        group.objectId=undefined
        group.createAt=undefined
        group.updateAt=undefined

        console.debug(JSON.stringify(group))
        var callback=function(xhr){
            if (xhr.readyState === XMLHttpRequest.HEADRES_RECEIVED) {
                console.log("Headers -->")
                console.log(xhr.getALLResponseHeaders())
            } else if (xhr.readyState === XMLHttpRequest.DONE) {
                console.log("responseText Got:" + xhr.responseText)
                if (xhr.status === 200) {
        emit:updateGroupInfoSuccessed(xhr.responstText)
                } else {
                    emit:updateGroupInfoFailed(xhr.responseText)
                }
                }
        }


        doNetwork("PUT",pri_var.groupUrl+"/"+group.objectId,JSON.stringify(group),callback)
    }
}
